package com.miage.kangourou.client.calendar;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.bradrydzewski.gwt.calendar.client.Appointment;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;
import com.miage.kangourou.client.Const;
import com.miage.kangourou.client.GetListesService;
import com.miage.kangourou.client.GetListesServiceAsync;
import com.miage.kangourou.client.beans.Enseignant;
import com.miage.kangourou.client.beans.Evenement;
import com.miage.kangourou.client.beans.Groupe;
import com.miage.kangourou.client.beans.Matiere;
import com.miage.kangourou.client.beans.Promo;
import com.miage.kangourou.client.beans.Salle;
import com.miage.kangourou.client.beans.TypeEvenement;
import com.miage.kangourou.client.beans.Ue;

public class PopupActionEvent {
	private int id_groupe;
	private int id_matiere;
	private final DialogBox dialogBox = new DialogBox();
	private final boolean databaseConnections[] = new boolean[7];

	private final Grid grid = new Grid(8, 4);

	// creation service
	private final GetListesServiceAsync getListesService = GWT
			.create(GetListesService.class);

	private final void checkBoxState(int dataType) {
		if ((dataType >= 0) && (dataType < databaseConnections.length)) {
			databaseConnections[dataType] = true;

			boolean enableBox = true;

			for (int i = 0; i < databaseConnections.length; ++i) {
				if (databaseConnections[i] == false) {
					enableBox = false;
					break;
				}
			}

			if (enableBox) {
				dialogBox.center();
				dialogBox.show();
			}
		}
	}

	public DialogBox show(Appointment event, final KangourouPanel context) {
		final int id = Integer.parseInt(event.getId());

		// initiate the async connections to false
		// will show the form only after all the 7 fields have been filled
		for (int i = 0; i < databaseConnections.length; ++i) {
			databaseConnections[i] = false;
		}

		final ListBox typeListBox = new ListBox();
		final ListBox ueListBox = new ListBox();
		final ListBox matiereListBox = new ListBox();
		final ListBox promoListBox = new ListBox();
		final ListBox groupeListBox = new ListBox();
		final ListBox professeurListBox = new ListBox();
		final ListBox salleListBox = new ListBox();

		grid.setWidget(0, 1, typeListBox);
		grid.setWidget(1, 1, ueListBox);
		grid.setWidget(2, 1, matiereListBox);
		grid.setWidget(3, 1, promoListBox);
		grid.setWidget(4, 1, groupeListBox);
		grid.setWidget(5, 1, professeurListBox);
		grid.setWidget(6, 1, salleListBox);

		/**
		 * Retrieve data from the database
		 */
		final AsyncCallback<List<TypeEvenement>> listeTypes = new AsyncCallback<List<TypeEvenement>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());
			}

			public void onSuccess(List<TypeEvenement> result) {

				for (TypeEvenement type : result) {

					typeListBox.addItem(type.getTypeEvenement(), String
							.valueOf(type.getId_type()));
				}

				checkBoxState(0);
			}
		};
		getListesService.getTypeList(listeTypes);

		final AsyncCallback<List<Enseignant>> listeProfs = new AsyncCallback<List<Enseignant>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());
			}

			public void onSuccess(List<Enseignant> result) {

				for (Enseignant enseignant : result) {

					professeurListBox.addItem(enseignant.getNom(), String
							.valueOf(enseignant.getId_enseignant()));
				}

				checkBoxState(1);
			}
		};
		getListesService.getEnseignantList(listeProfs);

		final AsyncCallback<List<Promo>> listePromos = new AsyncCallback<List<Promo>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());
			}

			public void onSuccess(List<Promo> result) {

				for (Promo promo : result) {

					promoListBox.addItem(promo.getIntitule(), String
							.valueOf(promo.getId_promo()));
				}

				checkBoxState(2);
			}
		};
		getListesService.getPromoList(listePromos);

		final AsyncCallback<List<Groupe>> Cgroupe = new AsyncCallback<List<Groupe>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());

			}

			public void onSuccess(List<Groupe> result) {
				groupeListBox.clear();
				for (Groupe groupe : result) {
					groupeListBox.addItem(groupe.getIntitule(), String
							.valueOf(groupe.getId_groupe()));
				}

				checkBoxState(3);
			}
		};

		promoListBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {

				getListesService.getGroupeListFromUe(Integer
						.parseInt(promoListBox.getValue(promoListBox
								.getSelectedIndex())), Cgroupe);

			}
		});

		final AsyncCallback<List<Salle>> listeSalle = new AsyncCallback<List<Salle>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());

			}

			public void onSuccess(List<Salle> result) {

				for (Salle salle : result) {

					salleListBox.addItem(salle.getIntitule(), String
							.valueOf(salle.getId_salle()));
				}

				checkBoxState(4);
			}
		};
		getListesService.getSalleList(listeSalle);

		final AsyncCallback<List<Ue>> listeUes = new AsyncCallback<List<Ue>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());

			}

			public void onSuccess(List<Ue> result) {

				for (Ue ue : result) {
					ueListBox.addItem(ue.getIntitule(), String.valueOf(ue
							.getId_ue()));
				}

				checkBoxState(5);
			}
		};
		getListesService.getUEList(listeUes);

		final AsyncCallback<List<Matiere>> Cmatiere = new AsyncCallback<List<Matiere>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());
			}

			public void onSuccess(List<Matiere> result) {
				matiereListBox.clear();
				for (Matiere matiere : result) {
					matiereListBox.addItem(matiere.getIntitule(), String
							.valueOf(matiere.getId_matiere()));
				}

				checkBoxState(6);
			}
		};

		ueListBox.addChangeHandler(new ChangeHandler() {
			public void onChange(ChangeEvent event) {
				getListesService.getMatiereListFromUe(Integer
						.parseInt(ueListBox.getValue(ueListBox
								.getSelectedIndex())), Cmatiere);
			}
		});

		dialogBox.setText("MODIFICATION EVENEMENT");

		grid.setWidget(0, 0, new Label("Type"));
		grid.setWidget(1, 0, new Label("Ue"));
		grid.setWidget(2, 0, new Label("Matiere"));
		grid.setWidget(3, 0, new Label("Promo"));
		grid.setWidget(4, 0, new Label("Groupe"));
		grid.setWidget(5, 0, new Label("Professeur"));
		grid.setWidget(6, 0, new Label("Salle"));
		/**
		 * Right panel
		 */
		Label dateDebutLabel = new Label("Date début");
		Label dateFinLabel = new Label("Date fin");
		Label commentaireLabel = new Label("Commentaire");

		grid.setWidget(0, 2, dateDebutLabel);
		grid.setWidget(1, 2, dateFinLabel);
		grid.setWidget(2, 2, commentaireLabel);

		final DateBox dateDebut = new DateBox();
		dateDebut.setValue(new Date());
		dateDebut.setFormat(new DateBox.DefaultFormat(DateTimeFormat
				.getShortDateFormat()));

		final ListBox heureDebut = new ListBox();
		for (int i = Const.CALENDAR_DISPLAY_START_H; i <= Const.CALENDAR_DISPLAY_STOP_H; ++i) {
			heureDebut.addItem(String.valueOf(i), String.valueOf(i));
		}

		final ListBox minDebut = new ListBox();
		for (int i = Const.CALENDAR_DISPLAY_START_MIN; i < 60; i += Const.CALENDAR_DISPLAY_INTERVAL_MIN) {
			minDebut.addItem(String.valueOf(i), String.valueOf(i));
		}

		HorizontalPanel dateDebutPanel = new HorizontalPanel();

		dateDebutPanel.add(dateDebut);
		dateDebutPanel.add(heureDebut);
		dateDebutPanel.add(minDebut);

		final DateBox dateFin = new DateBox();
		dateFin.setValue(new Date());
		dateFin.setFormat(new DateBox.DefaultFormat(DateTimeFormat
				.getShortDateFormat()));

		final ListBox heureDebut2 = new ListBox();
		for (int i = Const.CALENDAR_DISPLAY_START_H; i <= Const.CALENDAR_DISPLAY_STOP_H; ++i) {
			heureDebut2.addItem(String.valueOf(i), String.valueOf(i));
		}

		final ListBox minDebut2 = new ListBox();
		for (int i = Const.CALENDAR_DISPLAY_START_MIN; i < 60; i += Const.CALENDAR_DISPLAY_INTERVAL_MIN) {
			minDebut2.addItem(String.valueOf(i), String.valueOf(i));
		}

		HorizontalPanel dateFinPanel = new HorizontalPanel();

		dateFinPanel.add(dateFin);
		dateFinPanel.add(heureDebut2);
		dateFinPanel.add(minDebut2);

		final TextArea commentText = new TextArea();
		commentText.setVisibleLines(1);
		commentText.setWidth("100%");

		final Label responseMessage = new Label();
		responseMessage.setWidth("100%");
		responseMessage
		.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

		grid.setWidget(0, 3, dateDebutPanel);
		grid.setWidget(1, 3, dateFinPanel);
		grid.setWidget(2, 3, commentText);

		/**
		 * Recursion of the event
		 */
		grid.setWidget(3, 2, new Label("Répétition"));

		// Recursion - start date
		HorizontalPanel recursionDateStart = new HorizontalPanel();
		final DateBox recursionDateStartDateBox = new DateBox();
		recursionDateStartDateBox.setFormat(new DateBox.DefaultFormat(
				DateTimeFormat.getShortDateFormat()));
		recursionDateStart.add(new Label("Date début: "));
		recursionDateStart.add(recursionDateStartDateBox);
		grid.setWidget(3, 3, recursionDateStart);

		// Recursion - end date
		HorizontalPanel recursionDateEnd = new HorizontalPanel();
		final DateBox recursionDateEndDateBox = new DateBox();
		recursionDateEndDateBox.setFormat(new DateBox.DefaultFormat(
				DateTimeFormat.getShortDateFormat()));
		recursionDateEnd.add(new Label("Date fin: "));
		recursionDateEnd.add(recursionDateEndDateBox);
		grid.setWidget(4, 3, recursionDateEnd);

		// Recursion - days
		HorizontalPanel recursionDays = new HorizontalPanel();
		recursionDays.setSpacing(2);
		final CheckBox lundi = new CheckBox("Lundi");
		final CheckBox mardi = new CheckBox("Mardi");
		final CheckBox mercredi = new CheckBox("Mercredi");
		final CheckBox jeudi = new CheckBox("Jeudi");
		final CheckBox vendredi = new CheckBox("Vendredi");
		final CheckBox samedi = new CheckBox("Samedi");

		recursionDays.add(lundi);
		recursionDays.add(mardi);
		recursionDays.add(mercredi);
		recursionDays.add(jeudi);
		recursionDays.add(vendredi);
		recursionDays.add(samedi);

		grid.setWidget(5, 3, recursionDays);

		final VerticalPanel footer = new VerticalPanel();
		footer.setWidth("100%");

		final AsyncCallback<Integer> eventCallback = new AsyncCallback<Integer>() {

			public void onFailure(Throwable caught) {
				responseMessage
						.setText("La Modification de l'évènement a échoué.");
				responseMessage.addStyleName("event-add-failure");
			}

			public void onSuccess(Integer result) {
				responseMessage.addStyleName("event-add-success");

				if (result == 1) {
					responseMessage.setText("L'évènement a été modifié !");
				} else {
					responseMessage.setText(result
							+ " évènements ont été modifiés !");
				}

				((CalendarWidget) context.getWidget("calendar")).update();

			}
		};

		final AsyncCallback<Evenement> eventinformation = new AsyncCallback<Evenement>() {

			public void onFailure(Throwable caught) {
				Window.alert("Erreur lors de l'appel serveur "
						+ caught.getMessage());
			}

			public void onSuccess(Evenement result) {

				System.out.println("id type = " + result.getId_type());
				for (int i = 0; i < typeListBox.getItemCount(); i++) {
					if (Integer.parseInt(typeListBox.getValue(i)) == result
							.getId_type()) {
						typeListBox.setSelectedIndex(i);
						break;
					}
				}

				System.out.println("id enseignant = "
						+ result.getId_enseignant());
				for (int i = 0; i < professeurListBox.getItemCount(); i++) {
					if (Integer.parseInt(professeurListBox.getValue(i)) == result
							.getId_enseignant()) {
						professeurListBox.setSelectedIndex(i);
						break;
					}
				}

				System.out.println("salle = " + result.getId_salle());
				for (int i = 0; i < salleListBox.getItemCount(); i++) {
					if (Integer.parseInt(salleListBox.getValue(i)) == result
							.getId_salle()) {
						salleListBox.setSelectedIndex(i);
						break;
					}
				}

				System.out.println("ue = " + result.getId_ue());
				for (int i = 0; i < ueListBox.getItemCount(); i++) {
					if (Integer.parseInt(ueListBox.getValue(i)) == result
							.getId_ue()) {
						ueListBox.setSelectedIndex(i);
						break;
					}
				}
				id_matiere = result.getId_matiere();
				getListesService.getMatiereListFromUe(Integer
						.parseInt(ueListBox.getValue(ueListBox
								.getSelectedIndex())), Cmatiere);

				System.out.println("promo = " + result.getId_promo());

				for (int i = 0; i < promoListBox.getItemCount(); i++) {
					if (Integer.parseInt(promoListBox.getValue(i)) == result
							.getId_promo()) {
						promoListBox.setSelectedIndex(i);
						break;
					}
				}
				id_groupe = result.getId_groupe();
				getListesService.getGroupeListFromUe(Integer
						.parseInt(promoListBox.getValue(promoListBox
								.getSelectedIndex())), Cgroupe);

				dateDebut.setValue(result.getStart());

				for (int i = 0; i < heureDebut.getItemCount(); i++) {
					if (Integer.parseInt(heureDebut.getValue(i)) == result
							.getStart().getHours()) {
						heureDebut.setSelectedIndex(i);
						break;
					}
				}

				for (int i = 0; i < minDebut.getItemCount(); i++) {
					if (Integer.parseInt(minDebut.getValue(i)) == result
							.getStart().getMinutes()) {
						minDebut.setSelectedIndex(i);
						break;
					}
				}
				dateFin.setValue(result.getEnd());
				for (int i = 0; i < heureDebut2.getItemCount(); i++) {
					if (Integer.parseInt(heureDebut2.getValue(i)) == result
							.getEnd().getHours()) {
						heureDebut2.setSelectedIndex(i);
						break;
					}
				}

				for (int i = 0; i < minDebut2.getItemCount(); i++) {
					if (Integer.parseInt(minDebut2.getValue(i)) == result
							.getEnd().getMinutes()) {
						minDebut2.setSelectedIndex(i);
						break;
					}
				}

				if (result.isEventRecurrent()) {
					recursionDateStartDateBox.setValue(result
							.getRecurrence_debut());
					recursionDateEndDateBox
							.setValue(result.getRecurrence_fin());

					ArrayList<Integer> joursCoches = (ArrayList<Integer>) result
							.getRecurrence_jours();

					if (joursCoches.contains(1)) {
						lundi.setValue(true);
					}

					if (joursCoches.contains(2)) {
						mardi.setValue(true);
					}

					if (joursCoches.contains(3)) {
						mercredi.setValue(true);
					}

					if (joursCoches.contains(4)) {
						jeudi.setValue(true);
					}

					if (joursCoches.contains(5)) {
						vendredi.setValue(true);
					}

					if (joursCoches.contains(6)) {
						samedi.setValue(true);
					}
				}
			}
		};
		getListesService.findById(id, eventinformation);

		Button validateEventModification = new Button("Modifier",
				new ClickHandler() {
					public void onClick(ClickEvent event) {

						Date startDate = dateDebut.getValue();
						startDate.setHours(Integer.parseInt(heureDebut
								.getValue(heureDebut.getSelectedIndex())));
						startDate.setMinutes(Integer.parseInt(minDebut
								.getValue(minDebut.getSelectedIndex())));

						Date endDate = dateFin.getValue();
						endDate.setHours(Integer.parseInt(heureDebut2
								.getValue(heureDebut2.getSelectedIndex())));
						endDate.setMinutes(Integer.parseInt(minDebut2
								.getValue(minDebut2.getSelectedIndex())));

						boolean isAtLeastOnDayChecked = lundi.getValue()
								|| mardi.getValue() || mercredi.getValue()
								|| jeudi.getValue() || vendredi.getValue()
								|| samedi.getValue();

						if ((recursionDateEndDateBox.getValue() == null)
								|| (recursionDateStartDateBox.getValue() == null)
								|| (isAtLeastOnDayChecked == false)) {

							Evenement evt = new Evenement(id, Integer
									.parseInt(salleListBox
											.getValue(salleListBox
													.getSelectedIndex())),
									Integer.parseInt(typeListBox
											.getValue(typeListBox
													.getSelectedIndex())),
									Integer.parseInt(professeurListBox
											.getValue(professeurListBox
													.getSelectedIndex())),
									Integer.parseInt(matiereListBox
											.getValue(matiereListBox
													.getSelectedIndex())),
									Integer.parseInt(groupeListBox
											.getValue(groupeListBox
													.getSelectedIndex())),
									commentText.getValue(), startDate, endDate,
									0);
							getListesService.updateEvent(evt, eventCallback);

						} else {

							if (recursionDateStartDateBox.getValue().after(
									recursionDateEndDateBox.getValue())) {
								responseMessage
										.addStyleName("event-add-failure");
								responseMessage
										.setText("La date de fin doit être après la date de début!");
							} else {

								ArrayList<Integer> joursCoches = new ArrayList<Integer>();

								if (lundi.getValue()) {
									joursCoches.add(1);
								}

								if (mardi.getValue()) {
									joursCoches.add(2);
								}

								if (mercredi.getValue()) {
									joursCoches.add(3);
								}

								if (jeudi.getValue()) {
									joursCoches.add(4);
								}

								if (vendredi.getValue()) {
									joursCoches.add(5);
								}

								if (samedi.getValue()) {
									joursCoches.add(6);
								}

								Evenement evtRecurrent = new Evenement(0,
										Integer.parseInt(salleListBox
												.getValue(salleListBox
														.getSelectedIndex())),
										Integer.parseInt(typeListBox
												.getValue(typeListBox
														.getSelectedIndex())),
										Integer.parseInt(professeurListBox
												.getValue(professeurListBox
														.getSelectedIndex())),
										Integer.parseInt(matiereListBox
												.getValue(matiereListBox
														.getSelectedIndex())),
										Integer.parseInt(groupeListBox
												.getValue(groupeListBox
														.getSelectedIndex())),
										commentText.getValue(), startDate,
										endDate, 0);

								// eventService.createEventRecurrence(evtRecurrent,
								// recursionDateStartDateBox.getValue(),
								// recursionDateEndDateBox.getValue(),
								// joursCoches, eventCallback);
							}
						}
					}
				});
				
						final AsyncCallback<Boolean> deleteEventCallback = new AsyncCallback<Boolean>() {

			public void onFailure(Throwable caught) {
				responseMessage.setText("Erreur lors de la suppression de l'�v�nement (RPC) !");
				responseMessage.addStyleName("event-add-failure");
			}

			public void onSuccess(Boolean result) {

				if (result) {
					responseMessage.addStyleName("event-add-success");
					responseMessage.setText("L'�v�nement("+id+") � �t� supprim�");
				} else {
					responseMessage.addStyleName("event-add-failure");
					responseMessage.setText("Erreur lors de la suppression de l'�v�nement (SQL) !");
				}

				((CalendarWidget)context.getWidget("calendar")).update();

			}
		};

		Button validateEventSuppresion = new Button("Supprimer",
				new ClickHandler() {
					public void onClick(ClickEvent event) {
				List<Integer> idsEventsToDelete = new ArrayList<Integer>();
				idsEventsToDelete.add(id);
				getListesService.deleteEvents(idsEventsToDelete, deleteEventCallback);
					}
				});

		Button cancelEvent = new Button("Annuler", new ClickHandler() {
			public void onClick(ClickEvent event) {
				dialogBox.hide();
			}
		});

		HorizontalPanel boutonsActionsEvenement = new HorizontalPanel();

		boutonsActionsEvenement.setWidth("100%");
		boutonsActionsEvenement.add(validateEventModification);
		boutonsActionsEvenement.add(validateEventSuppresion);
		boutonsActionsEvenement.add(cancelEvent);

		boutonsActionsEvenement.setCellWidth(validateEventModification, "50%");
		boutonsActionsEvenement.setCellWidth(cancelEvent, "50%");

		boutonsActionsEvenement.setCellHorizontalAlignment(
				validateEventModification, HasHorizontalAlignment.ALIGN_RIGHT);
		boutonsActionsEvenement.setCellHorizontalAlignment(cancelEvent,
				HasHorizontalAlignment.ALIGN_LEFT);

		boutonsActionsEvenement.setBorderWidth(1);

		footer.add(boutonsActionsEvenement);
		footer.add(responseMessage);
		footer.setCellHorizontalAlignment(boutonsActionsEvenement,
				HasHorizontalAlignment.ALIGN_RIGHT);
		footer.setCellHorizontalAlignment(responseMessage,
				HasHorizontalAlignment.ALIGN_LEFT);

		VerticalPanel container = new VerticalPanel();
		container.add(grid);
		container.add(footer);
		container.setWidth("100%");

		dialogBox.add(container);

		return dialogBox;
	}

}
